package com.xuhui.xuaiagent.app;

import com.xuhui.xuaiagent.Advisor.MyLoggerAdvisor;
import com.xuhui.xuaiagent.Rag.LoveAppRagCloudAdvisorConfig;
import com.xuhui.xuaiagent.chatmemory.FileBasedChatMemory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.client.advisor.QuestionAnswerAdvisor;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.tool.ToolCallback;
import org.springframework.ai.tool.ToolCallbackProvider;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Flux;


import javax.annotation.Resource;

import static org.springframework.ai.chat.client.advisor.AbstractChatMemoryAdvisor.CHAT_MEMORY_CONVERSATION_ID_KEY;
import static org.springframework.ai.chat.client.advisor.AbstractChatMemoryAdvisor.CHAT_MEMORY_RETRIEVE_SIZE_KEY;


/**
 * @author 21829
 */
@Component
@Slf4j
public class CodeApp {

    private final ChatClient chatClient;
    //系统预设
    private static final String SYSTEM_PROMPT = "你是一名专业的 AI编程大师，精通Python、JavaScript、Java、C++等主流语言，熟悉算法、数据结构、前后端开发、DevOps和最新AI技术（如LLM、RAG）。" +
            "你的任务是帮助用户高效解决编程问题，提供 简洁、准确、可运行 的代码，同时解释技术原理，培养用户的编程思维。" +
            "核心能力:" +
            "代码生成：根据需求生成完整、可执行的代码，标注关键逻辑。\n" +
            "\n" +
            "代码优化：分析现有代码，提出性能、可读性、安全性的改进方案。\n" +
            "\n" +
            "错误调试：快速定位报错原因，提供修复建议。\n" +
            "\n" +
            "技术教学：用通俗语言解释复杂概念（如递归、闭包、并发模型）。\n" +
            "\n" +
            "工具链推荐：推荐适合的框架、库或开发工具（如VS Code插件、CI/CD工具）。" +
            "交互规则:" +
            "明确需求：若用户需求模糊，主动提问澄清（如：“需要什么语言？”或“目标场景是？”）。\n" +
            "\n" +
            "分步响应：复杂问题拆解为步骤，附代码示例和流程图/伪代码（如需）。\n" +
            "\n" +
            "安全提示：对可能的风险（如SQL注入、内存泄漏）给出警告。\n" +
            "\n" +
            "持续学习：若遇到未知技术，诚实回答并尝试基于逻辑推理提供建议。" +
            "风格要求:" +
            "语言：中文为主，技术术语保留英文（如async/await）。\n" +
            "\n" +
            "格式：代码用Markdown代码块标注语言类型（如```python），关键行加注释。\n" +
            "\n" +
            "态度：专业但友好，避免说教，鼓励用户动手实践。";

    public CodeApp(ChatModel dashscopeChatModel) {
        //基于内存的ai对话上下文记忆功能
        String dir = System.getProperty("user.dir") + "/tmp/chatMemory";
        ChatMemory chatMemory = new FileBasedChatMemory(dir);
        //使用构建者模式指定模型设置系统预设和顾问注入ai对话客户端
        chatClient = ChatClient.builder(dashscopeChatModel)
                .defaultSystem(SYSTEM_PROMPT)
                .defaultAdvisors(
                        new MessageChatMemoryAdvisor(chatMemory),
                        new MyLoggerAdvisor()
                )
                .build();
    }


    public String doChat(String message, String chatId) {
        ChatResponse chatResponse = chatClient
                .prompt()
                .user(message)
                .advisors(advisorSpec -> advisorSpec.param(CHAT_MEMORY_CONVERSATION_ID_KEY, chatId)
                        .param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 10))
                .call()
                .chatResponse();
        String content = chatResponse.getResult().getOutput().getText();
        return content;
    }

    @Resource
    private VectorStore loveAppVectorStore;

    @Resource
    private LoveAppRagCloudAdvisorConfig loveAppRagCloudAdvisor;

    /**
     * 和rag知识库进行对话
     *
     * @param message
     * @param chatId
     * @return
     */
    public String doChatWithRah(String message, String chatId) {
        ChatResponse chatResponse = chatClient.prompt()
                .user(message)
                .advisors(advisorSpec -> advisorSpec.param(CHAT_MEMORY_CONVERSATION_ID_KEY, chatId)
                        .param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 10))
                .advisors(new MyLoggerAdvisor())
                .advisors(new QuestionAnswerAdvisor(loveAppVectorStore))
                .call()
                .chatResponse();
        String content = chatResponse.getResult().getOutput().getText();
        return content;
    }

    @Resource
    private ToolCallback[] allTools;

    public String doChatWithTools(String message, String chatId) {
        ChatResponse chatResponse = chatClient.prompt()
                .user(message)
                .advisors(advisorSpec -> advisorSpec.param(CHAT_MEMORY_CONVERSATION_ID_KEY, chatId)
                        .param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 10))
                .advisors(new MyLoggerAdvisor())
                .tools(allTools)
                .call()
                .chatResponse();
        String content = chatResponse.getResult().getOutput().getText();
        return content;
    }

    @Resource
    private ToolCallbackProvider toolCallbackProvider;

    public String doChatWithMcp(String message, String chatId) {
        ChatResponse chatResponse = chatClient.prompt()
                .user(message)
                .advisors(advisorSpec -> advisorSpec.param(CHAT_MEMORY_CONVERSATION_ID_KEY, chatId)
                        .param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 10))
                .advisors(new MyLoggerAdvisor())
                .tools(toolCallbackProvider)
                .call()
                .chatResponse();
        String content = chatResponse.getResult().getOutput().getText();
        return content;
    }

    public Flux<String> doChatByStream(String message, String chatId) {
        return chatClient.prompt()
                .user(message)
                .advisors(advisorSpec -> advisorSpec.param(CHAT_MEMORY_CONVERSATION_ID_KEY, chatId)
                        .param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 10))
                .advisors(new QuestionAnswerAdvisor(loveAppVectorStore))
                .stream()
                .content();
    }
}
